package ui.swing.popup;

import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class RightClickGlassPane extends JComponent implements MouseListener,
		MouseMotionListener {

	private static final long serialVersionUID = 5291764782131659608L;

	private JPopupMenu popup;
	private Container contentPane;

	public RightClickGlassPane(Container contentPane, JPopupMenu menu) {
		this.contentPane = contentPane;
		popup = menu;

		addMouseListener(this);
		addMouseMotionListener(this);
	}

	// overrides the paint() method to do nothing, ensuring that the glass pane
	// is invisible.
	public void paint(Graphics g) {
	}

	private void redispatchMouseEvent(MouseEvent e, boolean repaint) {
		// if it's a pop up
		if (e.isPopupTrigger()) {
			// show the pop up and return
			popup.show(e.getComponent(), e.getX(), e.getY());
		} else {
			// since it's not a pop up we need to re-dispatch it.
			// get the mouse click point relative to the content pane
			Point containerPoint = SwingUtilities.convertPoint(this, e
					.getPoint(), contentPane);

			// find the component that is under this point
			Component component = SwingUtilities.getDeepestComponentAt(
					contentPane, containerPoint.x, containerPoint.y);

			// return if nothing was found
			if (component == null) {
				return;
			}

			// convert point relative to the target component
			Point componentPoint = SwingUtilities.convertPoint(this, e
					.getPoint(), component);

			// re-dispatch the event
			component.dispatchEvent(new MouseEvent(component, e.getID(), e
					.getWhen(), e.getModifiers(), componentPoint.x,
					componentPoint.y, e.getClickCount(), e.isPopupTrigger()));

		}
	}

	// catch all mouse events and re-dispatch them
	public void mouseMoved(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}

	public void mouseDragged(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}

	public void mouseClicked(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}

	public void mouseEntered(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}

	public void mouseExited(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}

	public void mousePressed(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}

	public void mouseReleased(MouseEvent e) {
		redispatchMouseEvent(e, false);
	}
	
	public static void main(String[] args) {
		// create a frame with some components in it
		JFrame frame = new JFrame("Right Click Test");
		JButton button = new JButton("this is a button");
		JTextField tf = new JTextField("this is a textfield");
		JPanel panel = new JPanel();
		panel.add(button);
		panel.add(tf);
		frame.getContentPane().add(panel);

		JPopupMenu popup = new JPopupMenu();
		popup.add(new JMenuItem("Dogs"));
		popup.add(new JMenuItem("Cats"));
		popup.add(new JMenuItem("Mass Hysteria"));
		
		// create the right-click glass pane.
		Component rc = new RightClickGlassPane(frame.getContentPane(),popup);
		// set as glass pane and make it visible
		frame.setGlassPane(rc);
		rc.setVisible(true);
		
		// pack and show the frame
		frame.pack();
		frame.setSize(400,200);
		frame.setVisible(true);
	}

}
